package org.example.backend.service.impl;

import lombok.RequiredArgsConstructor;
import org.example.backend.dto.AnimalRoutePointDTO;
import org.example.backend.dto.RouteDTO;
import org.example.backend.entity.Animal;
import org.example.backend.entity.UserPreference;
import org.example.backend.repository.AnimalRepository;
import org.example.backend.service.RouteService;
import org.example.backend.service.UserPreferenceService;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class RouteServiceImpl implements RouteService {

    private final AnimalRepository animalRepository;
    private final UserPreferenceService userPreferenceService;

    @Override
    public RouteDTO generateRoute(Double startX, Double startY, Integer duration) {
        List<Animal> animals = animalRepository.findAll();
        return generateRouteFromAnimals(animals, startX, startY, duration);
    }

    @Override
    public RouteDTO generatePreferredRoute(Double startX, Double startY, Integer duration) {
        List<UserPreference> preferences = userPreferenceService.getCurrentUserPreferences();
        List<Animal> animals = animalRepository.findByCategories(
            preferences.stream()
                .map(pref -> pref.getCategory())
                .collect(Collectors.toList())
        );
        return generateRouteFromAnimals(animals, startX, startY, duration);
    }

    @Override
    public RouteDTO generateRecommendRoute(Double startX, Double startY, Integer duration) {
        List<Animal> animals = animalRepository.findByPopularity();
        return generateRouteFromAnimals(animals, startX, startY, duration);
    }

    private RouteDTO generateRouteFromAnimals(List<Animal> animals, Double startX, Double startY, Integer duration) {
        List<AnimalRoutePointDTO> points = new ArrayList<>();
        double totalDistance = 0;
        int totalDuration = 0;
        final double[] currentPosition = {startX, startY};

        animals = animals.stream()
                .sorted(Comparator.comparingDouble(a -> 
                    calculateDistance(currentPosition[0], currentPosition[1], 
                                   a.getLocationX(), a.getLocationY())))
                .collect(Collectors.toList());

        for (Animal animal : animals) {
            if (totalDuration >= duration) break;

            double distance = calculateDistance(currentPosition[0], currentPosition[1], 
                                             animal.getLocationX(), animal.getLocationY());
            
            AnimalRoutePointDTO point = new AnimalRoutePointDTO();
            point.setAnimal(animal);
            point.setOrder(points.size() + 1);
            point.setDistance(distance);
            point.setDuration(15); // 默认每个点停留15分钟

            points.add(point);
            totalDistance += distance;
            totalDuration += point.getDuration();

            currentPosition[0] = animal.getLocationX();
            currentPosition[1] = animal.getLocationY();
        }

        RouteDTO route = new RouteDTO();
        route.setPoints(points);
        route.setTotalDistance(totalDistance);
        route.setTotalDuration(totalDuration);

        return route;
    }

    private double calculateDistance(double x1, double y1, double x2, double y2) {
        return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
    }
}
